﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GameLibrary.AI
{
    using Tile;

    /// <summary>
    /// Return best place to build village in a region by give labors.
    /// </summary>
   public static class SelectTheBestPositionToBuildVillageInACity
    {
      public struct node:IComparable<node>
       {
         public  Position pos;
         public  double fitness;
         public  node(Position pos, double fitness)
           {
               this.pos = pos;
               this.fitness = fitness;
           }
         #region IComparable<node> Members

         public int CompareTo(node other)
         {
             return other.fitness.CompareTo(this.fitness);
         }

         #endregion
       }
       /// <summary>
       /// Return labor and best position pairs
       /// </summary>
       /// <param name="units"></param>
       /// <param name="candidateList"></param>
       /// <param name="budget"></param>
       /// <returns></returns>
       public static Dictionary<uint,Position> Select(
           Dictionary<uint,Position> units, 
           Dictionary<Position,TileType> candidateList
           )
       {
           Dictionary<uint, Position> VillagePositions = new Dictionary<uint, Position>();
           foreach (var u in units)
           {
               List<node> list = new List<node>(candidateList.Count);
               foreach (var a in candidateList)
               {
                   list.Add(new node
                   {
                       pos = a.Key,
                       fitness = GetFitness(
                               a.Value.BaseProduction,     // natural goods.
                               a.Key.FindDistance(u.Value), // how far away from this position count as 1 ap per move.
                               a.Value.BaseMoveCost //there are no village on that map.
                             )
                       // approx estimate.
                   });
               }
               list.Sort();
               VillagePositions.Add(u.Key, list[0].pos);
               candidateList.Remove(list[0].pos);
               if (candidateList.Count <= 0) // don't search nothing.
                   break;
           }
           return VillagePositions;
       }

       private static double GetFitness(
           uint production, 
           double distance,
           double moveCost)
       {
           return production / (distance * moveCost);
       }
    }
}
